#include <iostream>
#define BLACK true
#define RED false
using namespace std;
template <typename T>
struct Node{
T key;
bool color;
Node<T> *p, *left, *right;
Node(int _key): key(_key) {}
Node(int _key, bool _color): key(_key), color(_color) {}
};
template <typename T>
class RBTree{
public:
RBTree(void){
nil=new Node<T>(-1);
}
Node<T>* Minimum(Node<T>* x){
while(x->left!=this->nil) x=x->left;
return x;
}
void LeftRotate(Node<T>* x){
Node<T>* y=x->right;
x->right=y->left;
if(y->left==this->nil) y->left->p=x;
y->p=x->p;
if(x->p==this->nil) this->root=y;
else if(x==x->p->left) x->p->left=y;
else x->p->right=y;
y->left=x;
x->p=y;
}
void RightRotate(Node<T>* y){
Node<T>* x=y->left;
y->left=x->right;
if(x->right==this->nil) x->right->p=y;
x->p=y->p;
if(y->p==this->nil) this->root=x;
else if(y==y->p->right) y->p->right=x;
else y->p->left=x;
x->right=y;
y->p=x;
}
void RBInsertFixup(Node<T>* z){
Node<T>* y;
while(z->p->color==RED){
if(z->p==z->p->p->left){
y=z->p->p->right;
if(y->color==RED){
z->p->color=BLACK;
y->color=BLACK;
z->p->p->color=RED;
z=z->p->p;
} else if(z==z->p->right){
z=z->p;
LeftRotate(z);
} else {
z->p->color=BLACK;
z->p->p->color=RED;
RightRotate(z->p->p);
}
} else {
y=z->p->p->left;
if(y->color==RED){
y->p->color=BLACK;
y->color=BLACK;
z->p->p->color=RED;
z=z->p->p;
} else if(z==z->p->left){
z=z->p;
RightRotate(z);
} else {
z->p->color=BLACK;
z->p->p->color=RED;
LeftRotate(z->p->p);
}
}
}
this->root->color=BLACK;
}
void Insert(int key){
Node<T>* z=new Node<T>(key, RED);
Node<T> *x, *y;
x=this->nil; y=this->root;
while(x!=this->nil){
y=x;
if(z->key<x->key) x=x->left;
else x=x->right;
}
z->p=y;
if(y==this->nil) this->root=z;
else if(z->key<y->key) y->left=z;
else y->right=z;
z->left=this->nil;
z->right=this->nil;
RBInsertFixup(z);
}
void Transplant(Node<T>* u, Node<T>* v){
if(u->p==this->nil) this->root=v;
else if(u==u->p->left) u->p->left=v;
else u->p->right=v;
v->p=u->p;
}
void DeleteFixup(Node<T>* x){
Node<T>* w;
while(x!=this->root && x->color==BLACK){
if(x==x->p->left){
w=x->p->right;
if(w->color==RED){
w->color=BLACK;
x->p->color=RED;
LeftRotate(x->p);
w=x->p->right;
}
if(w->left->color==BLACK && w->right->color==BLACK){
w->color=RED;
x=x->p;
} else if(w->right->color==BLACK){
w->left->color=BLACK;
w->color=RED;
RightRotate(w);
w=x->p->right;
} else {
w->color=x->p->color;
x->p->color=BLACK;
w->right->color=BLACK;
LeftRotate(x->p);
x=this->root;
}
} else {
w=x->p->left;
if(w->color==RED){
w->color=BLACK;
x->p->color=RED;
RightRotate(x->p);
w=x->p->left;
}
if(w->right->color==BLACK && w->left->color==BLACK){
w->color=RED;
x=x->p;
} else if(w->left->color==BLACK){
w->right->color=BLACK;
w->color=RED;
LeftRotate(w);
w=x->p->left;
} else {
w->color=x->p->color;
x->p->color=BLACK;
w->left->color=BLACK;
RightRotate(x->p);
x=this->root;
}
}
}
x->color=BLACK;
}
void Delete(Node<T>* z){
Node<T>* x;
Node<T>* y=z;
bool y_original_color=y->color;
if(z->left==this->nil){
x=z->right;
Transplant(z, z->right);
} else if(z->right==this->nil){
x=z->left;
Transplant(z, z->left);
} else {
y=Minimum(z->right);
y_original_color=y->color;
x=y->right;
if(y->p==z) x->p=y;
else{
Transplant(y, y->right);
y->right=z->right;
y->right->p=y;
}
Transplant(z, y);
y->left=z->lef;
y->left->p=y;
y->color=z->color;
}
if(y_original_color==BLACK) DeleteFixup(x);
delete z;
}
private:
Node<T> *root, *nil;
};